package z1cvt

import (
	"bytes"
	"encoding/json"
	"fmt"
	"strconv"
	"strings"
	"time"

	"gitee.com/z1gotool/z1err"
)

type StrTo string

func (s StrTo) String() string {
	return string(s)
}

func (s StrTo) Int() (int, error) {
	v, err := strconv.Atoi(s.String())
	return v, err
}

func (s StrTo) MustInt() int {
	v, _ := s.Int()
	return v
}

func (s StrTo) UInt32() (uint32, error) {
	v, err := strconv.Atoi(s.String())
	return uint32(v), err
}

func (s StrTo) MustUInt32() uint32 {
	v, _ := s.UInt32()
	return v
}

func (s StrTo) MustFloat32() float32 {
	v64, _ := strconv.ParseFloat(s.String(), 32)
	v32 := float32(v64)

	return v32
}

func (s StrTo) MustInt32() int32 {
	v64, _ := strconv.ParseInt(s.String(), 10, 32)
	v32 := int32(v64)

	return v32
}

func (s StrTo) MustString() string {
	return s.String()
}

func MustString(input interface{}) string {
	str := ``
	switch input.(type) {
	case nil:
		str = ``
	case []byte:
		str = fmt.Sprintf(`%v`, string(input.([]byte)))
	default:
		str = fmt.Sprintf(`%v`, input)
	}

	return str
}

func MustInt64(input interface{}) int64 {
	str := MustString(input)

	if strings.Contains(str, `e+`) {
		var newNum float64
		numStr := str
		_, err := fmt.Sscanf(numStr, "%e", &newNum)
		z1err.Check(err)
		str = fmt.Sprintf("%.f", newNum)
	}

	if str == `` {
		return 0
	}

	i, err := strconv.ParseInt(str, 10, 64)
	z1err.Check(err)

	return i
}

func MustFloat64(input interface{}) float64 {
	str := MustString(input)

	if str == `` {
		return 0
	}

	f, err := strconv.ParseFloat(str, 64)
	z1err.Check(err)

	return f
}

func MustInt8(input interface{}) int8 {
	str := MustString(input)
	if str == `` {
		return 0
	}
	int, err := strconv.ParseInt(str, 10, 8)
	z1err.Check(err)

	return int8(int)
}

func MustDateStr(timestrap interface{}) string {
	i := MustInt64(timestrap)

	if i == 0 {
		return ``
	}

	return time.Unix(i, 0).Format("2006-01-02 15:04:05")
}

func DateStr2timestrap(dateStr string) (timestrap int64) {
	if dateStr == `` {
		return 0
	}

	// 定义需转换的时间格式
	layout := "2006-01-02 15:04:05"

	// 定义需转换的时间字符串
	// dateStr = "2021-10-28 13:16:00"

	// 使用 Parse 将时间字符串转换为 Time 类型
	t, err := time.ParseInLocation(layout, dateStr, time.Local)
	z1err.Check(err)

	// 使用 Unix 函数将 Time 类型转换为时间戳
	timestrap = t.Unix()

	return
}

func Z1Unmarshal(data []byte, v any) (err error) {
	// 使用decoder方式反序列化，指定使用number类型,防止科学计数法
	decoder := json.NewDecoder(bytes.NewReader(data))
	decoder.UseNumber()
	err = decoder.Decode(&v)

	return
}

func FileSizeStr(size interface{}) (sizeStr string) {
	sizeStrT := MustString(size)
	sizeInt64 := MustFloat64(sizeStrT)

	G := float64(1024 * 1024 * 1024)
	M := float64(1024 * 1024)
	K := float64(1024)

	if sizeInt64 > G {
		sizeStr = fmt.Sprintf("%.2fG", sizeInt64/G)
	} else if sizeInt64 > M {
		sizeStr = fmt.Sprintf("%.2fM", sizeInt64/M)
	} else if sizeInt64 > K {
		sizeStr = fmt.Sprintf("%.2fK", sizeInt64/K)
	} else {
		sizeStr = fmt.Sprintf("%v", sizeInt64)
	}

	return
}

func MustTimestrap(strTime interface{}, format ...string) (ret int64) {
	defer z1err.Handle(nil, func(err error) {
		ret = 0
	})

	strTem := "2006-01-02 15:04:05"
	if len(format) > 0 {
		strTem = format[0]
	}
	//获取本地location
	timeLocal, err := time.LoadLocation("Local")
	z1err.Check(err)
	s := MustString(strTime)
	theTime, err := time.ParseInLocation(strTem, s, timeLocal)
	z1err.Check(err)
	return theTime.Unix()
}

func Placeholder() {}
